package indi.simple.pms.util;

import lombok.Getter;
import lombok.Setter;
import org.apache.poi.hpsf.DocumentSummaryInformation;
import org.apache.poi.hpsf.SummaryInformation;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.util.CellRangeAddress;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.function.Consumer;

/**
 * 类
 *
 * @author wanglunhui
 * @since 2022-05-17 09:59:57
 */
public class ExcelUtil {

    private final static int heightInPoints=25;

    @Getter
    @Setter
    public static class ExcelUtilBuilder{
        private HSSFWorkbook workbook;
        private HSSFSheet sheet;
        private HSSFCellStyle style;
        private OutputStream outputStream;
        private int[] columnWidths;
        private int nextRow=0;

        public ExcelUtilBuilder createWorkbook(){ // 创建sheet
            HSSFWorkbook workbook = new HSSFWorkbook();
            HSSFSheet sheet = workbook.createSheet();

            // 基本信息
            workbook.createInformationProperties();
            DocumentSummaryInformation dsi = workbook.getDocumentSummaryInformation();
            dsi.setCategory("类别:Excel文件");
            dsi.setManager("管理者:***");
            dsi.setCompany("公司:***有限公司");
            SummaryInformation si = workbook.getSummaryInformation();
            si.setSubject("主题:结果导出表");
            si.setTitle("标题:结果导出表");
            si.setAuthor("作者:***");
            si.setComments("备注:可打印");

            // 样式
            HSSFCellStyle style = workbook.createCellStyle();
            style.setAlignment(HorizontalAlignment.CENTER);
            style.setVerticalAlignment(VerticalAlignment.CENTER);
            style.setBorderTop(BorderStyle.THIN);
            style.setBorderBottom(BorderStyle.THIN);
            style.setBorderLeft(BorderStyle.THIN);
            style.setBorderRight(BorderStyle.THIN);

            this.workbook=workbook;
            this.sheet=sheet;
            this.style=style;

            return this;
        }

        public ExcelUtilBuilder preProcess(int[] columnWidths,String title){ // 预处理
            // 设置列宽度
            for (int i=0;i<columnWidths.length;i++){
                this.sheet.setColumnWidth(i,columnWidths[i]);
            }
            this.columnWidths=columnWidths;

            // 第0行
            HSSFRow row0 = sheet.createRow(this.getAndAddNextRow());
            row0.setHeightInPoints(heightInPoints);
            // 创建第0行的所有列
            for (int i=0;i<columnWidths.length;i++){
                HSSFCell cell=row0.createCell(i);
                cell.setCellStyle(style);
            }
            // 设置第0列的值
            HSSFCell cell=row0.getCell(0);
            cell.setCellValue(title);
            cell.setCellStyle(style);
            // 合并第0行的0到最后一列
            CellRangeAddress region=new CellRangeAddress(0,0,0,columnWidths.length-1);
            sheet.addMergedRegion(region);

            return this;
        }

        public int getAndAddNextRow(){
            return this.nextRow++;
        }

        public HSSFRow createRowAndAddNextRow(){
            HSSFRow row = sheet.createRow(this.getAndAddNextRow());
            row.setHeightInPoints(heightInPoints);

            return row;
        }

        public void createAndSetRowValues(HSSFRow row,String[] values){
            if(columnWidths.length!=values.length){
                throw new RuntimeException(String.format("columnWidths length: %d, values length: %d, not equal",columnWidths.length,values.length));
            }
            for (int i=0;i<values.length;i++){
                HSSFCell cell=row.createCell(i); // 创建列
                cell.setCellValue(values[i]); // 设置值
                cell.setCellStyle(style);
            }
        }

        public ExcelUtilBuilder apply(Consumer<ExcelUtilBuilder> consumer){
            consumer.accept(this);

            return this;
        }

        public void build(){
            try {
                workbook.write(outputStream);
                workbook.close();
                outputStream.close();
            }catch (Exception e){
                e.printStackTrace();
            }
        }

    }

    public static ExcelUtilBuilder builder(){
        return new ExcelUtilBuilder();
    }

    public static void main(String[] args) {
        String[][] data=new String[][]{
                {"1","admin","123456","男","1900-01-01","软件开发部","研发工程师"},
                {"2","test","123456","女","2000-01-01","软件开发部","测试工程师"}
        };
        ExcelUtil
                .builder()
                .createWorkbook()
                .preProcess(
                        new int[]{9 * 256, 27 * 256, 27 * 256, 9 * 256, 27 * 256, 27 * 256, 27 * 256},
                        "用户信息表"
                )
                .apply(excelUtilBuilder -> {
                    String[] columnNames={"ID","姓名","密码","性别","生日","部门","职位"};
                    // 第1行
                    HSSFRow row1 = excelUtilBuilder.createRowAndAddNextRow();
                    // 创建并设置所有列的值
                    excelUtilBuilder.createAndSetRowValues(row1,columnNames);
                })
                .apply(excelUtilBuilder -> {
                    // 其他行
                    for (String[] strings:data){
                        String[] columnNames={strings[0],strings[1],strings[2],strings[3],strings[4],strings[5],strings[6]};
                        // 创建行
                        HSSFRow row = excelUtilBuilder.createRowAndAddNextRow();
                        // 创建并设置所有列的值
                        excelUtilBuilder.createAndSetRowValues(row,columnNames);
                    }
                })
                .apply(excelUtilBuilder -> {
                    String path="./用户信息表.xlsx";
                    try {
                        OutputStream outputStream=new FileOutputStream(path);

                        excelUtilBuilder.setOutputStream(outputStream);
                    }catch (IOException e){
                        throw new RuntimeException(e);
                    }
                })
                .build();
    }

}

